#include <iostream>
#include <string>
#include <vector>
#include <limits>

#define EIGEN_SPARSEVECTOR_PLUGIN "MatrixCore/SparseVectorAddons.hpp"

#include <Eigen/Sparse>

#include <Parser/MPSReader.hpp>
#include <LinearProgramming/Presolve.hpp>

#include <LinearProgramming/LPSolver.hpp>

using namespace std;
using namespace green;

/*!
 * \brief getTestData
 * \return
 * FIXME Temporary method
 */
internal::Problem getTestData() {
  internal::Problem problem(2, 3);

  problem.b(0) = 1;
  problem.b(1) = 1;

  problem.c(0) = 1;
  problem.c(1) = 1;
  problem.c(2) = 1;

  problem.A.insert(0, 0) = 1;
  problem.A.insert(0, 1) = -1;
  problem.A.insert(1, 2) = 1;

  return problem;
}

/*!
 * \brief getTestData2
 * \return
 */
internal::Problem getTestData2() {
  internal::Problem problem(4, 6);

  problem.c(0) = -500;
  problem.c(1) = -300;
  problem.c(2) = 0;
  problem.c(3) = 0;
  problem.c(4) = 0;
  problem.c(5) = 0;

  problem.b(0) = 1200;
  problem.b(1) = 12;
  problem.b(2) = 10;
  problem.b(3) = 7;

  problem.A.insert(0, 0) = 200;
  problem.A.insert(0, 1) = 100;
  problem.A.insert(0, 2) = 1;

  problem.A.insert(1, 0) = 1;
  problem.A.insert(1, 1) = 2;
  problem.A.insert(1, 3) = 1;

  problem.A.insert(2, 0) = 1;
  problem.A.insert(2, 1) = 1;
  problem.A.insert(2, 4) = 1;

  problem.A.insert(3, 0) = 1;
  problem.A.insert(3, 1) = 1;
  problem.A.insert(3, 5) = -1;

  //    double norbc = 1 + (std::max(problem.c.maxCoeff(),
  // problem.b.maxCoeff()) -
  //                        std::min(problem.c.minCoeff(),
  // problem.b.minCoeff()));

  //    problem.c = problem.c / norbc;
  //    problem.b = problem.b / norbc;

  return problem;
}

/*!
 * \brief getTestData3
 * \return
 */
internal::Problem getTestData3() {
  internal::Problem problem(3, 5);

  problem.c(0) = -5;
  problem.c(1) = -6;
  problem.c(2) = 0;
  problem.c(3) = 0;
  problem.c(4) = 0;

  problem.b(0) = 10;
  problem.b(1) = 3;
  problem.b(2) = 35;

  problem.A.insert(0, 0) = 1;
  problem.A.insert(0, 1) = 1;
  problem.A.insert(0, 2) = 1;

  problem.A.insert(1, 0) = 1;
  problem.A.insert(1, 1) = -1;
  problem.A.insert(1, 3) = -1;

  problem.A.insert(2, 0) = 5;
  problem.A.insert(2, 1) = 4;
  problem.A.insert(2, 4) = 1;

  return problem;
}

/*!
 * \brief getTestData4
 * \return
 */
internal::Problem getTestData4() {
  internal::Problem problem(2, 4);

  problem.c(0) = -17.1667;
  problem.c(1) = -25.8667;
  problem.c(2) = 0;
  problem.c(3) = 0;

  problem.b(0) = 2270;
  problem.b(1) = 1900;

  problem.A.insert(0, 0) = 13;
  problem.A.insert(0, 1) = 19;
  problem.A.insert(0, 2) = 1;

  problem.A.insert(1, 0) = 20;
  problem.A.insert(1, 1) = 29;
  problem.A.insert(1, 3) = 1;

  return problem;
}
/*!
 * \brief main
 * \return
 * Test Driver
 */
int main() {

  //  std::string fileName{"/home/satya/Projects/Data/HelloWorld.mps"};

  //  fileName = "/home/satya/Projects/Data/hello.mps";

  //  // fileName = "/home/satya/Projects/Data/25fv47.mps";

  //  green::MPSReader mpsReader{fileName};

  //  green::Presolve<green::MPSReader> converter(mpsReader);

  //  converter.getConstraints();

  //  converter.standardize();
  //  cout << converter.getConstraints().cols() << "        "
  //       << converter.getConstraints().rows() << endl;
  //  cout << converter.getConstraints() << endl;

  green::LPSolver solver;

  solver.solve(getTestData());

  return 0;
}
